package com.david.trade.common;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Iterator;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author wangjijiang
 * @date 2020/10/22 21:04
 */
public class SimpleArray<T> {

    public volatile Object[] list;

    private ReentrantLock lock = new ReentrantLock();

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    private int delta = 8;

    private int canUseIndex = 0;

    private int removedIndex = 0;

    public SimpleArray(int capcity) {
        this(capcity, 8);
    }

    public SimpleArray(int capcity, int delta) {
        this.list = new Object[capcity];
        this.delta = delta;
    }

    public SimpleArray() {
        this(16, 8);
    }

    public void add(T t) {
        lock.lock();
        try {
            if (list[canUseIndex] == null) {
                list[canUseIndex] = t;
                canUseIndex = Math.min(canUseIndex + 1, this.list.length - 1);
                return;
            }
            if (list[removedIndex] == null) {
                list[removedIndex] = t;
                return;
            }
            for (int i = 0; i < this.list.length; i++) {
                if (list[i] == null) {
                    list[i] = t;
                    canUseIndex = Math.min(i + 1, this.list.length - 1);
                    return;
                }
            }
            Object[] newlist = new Object[list.length + this.delta];
            int i = 0;
            for (; i < this.list.length; i++) {
                newlist[i] = this.list[i];
            }
            newlist[i] = t;
            this.list = newlist;
            canUseIndex = Math.min(i + 1, this.list.length - 1);
        } catch (Exception e) {
            logger.error("add error", e);
        } finally {
            lock.unlock();
        }
    }

    public T get(int index) {
        if (index < 0 || index >= this.list.length) {
            throw new IllegalStateException("next error index not in range index=" + index + "length=" + list.length);
        }
        return (T) this.list[index];
    }

    public T remove(int index) {
        if (index < 0 || index >= this.list.length) {
            throw new IllegalStateException("next error index not in range index=" + index + "length=" + list.length);
        }
        T value = (T) this.list[index];
        this.list[index] = null;
        removedIndex = index;
        return value;
    }

    public void clear() {
        for (int i = 0; i < this.list.length; i++) {
            list[i] = null;
        }
    }

    public int size() {
        return this.list.length;
    }

    public Iterator<T> iterator() {
        return new Itr(this.list);
    }

    private class Itr implements Iterator<T> {

        public Object[] values;

        private int index;

        public Itr(Object[] values) {
            this.values = values;
        }

        @Override
        public boolean hasNext() {
            return index < this.values.length;
        }

        @Override
        public T next() {
            if (index < 0 || index >= this.values.length) {
                throw new IllegalStateException("next error index not in range index=" + index + "length=" + values.length);
            }
            return (T) values[index++];
        }

        public void remove() {
            if (index <= 0 || index > this.values.length) {
                throw new IllegalStateException("remove error not in range index=" + index + "length=" + values.length);
            }
            values[index - 1] = null;
        }
    }

}
